#include "Bsp_dac.h"

#include "Bsp_adc.h"

// clang-format off
USR_GPIO_Init dac_ctl_pin[]={
//PORT  pin             mode                outputType               pull       remapPin   analogSwitch 
 {GPIOB,{FL_GPIO_PIN_12,DAC_GPIO_MODE,FL_GPIO_OUTPUT_PUSHPULL,FL_DISABLE,FL_DISABLE,FL_DISABLE}},//OPA_OUT1
};
// clang-format on

/**
 * * @brief  ADC Interrupt Initialization function
 * @param  void
 * @retval None
 */
static void VREFP_Init(void)
{
    FL_VREFP_InitTypeDef VREFP_InitStruct = { 0 };
#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
    VREFP_InitStruct.voltageTrim =
        FL_VREFP_OUTPUT_VOLTAGE_1P5V_TRIM; /*电压trim值，对应outputVoltage输出的电压*/
    VREFP_InitStruct.outputVoltage = FL_VREFP_OUTPUT_VOLTAGE_1P5V; /*配置VREFP输出电压*/
#elif defined(HARD_VERSION_V2_1)
    VREFP_InitStruct.voltageTrim =
        FL_VREFP_OUTPUT_VOLTAGE_4P5V_TRIM; /*电压trim值，对应outputVoltage输出的电压*/
    VREFP_InitStruct.outputVoltage = FL_VREFP_OUTPUT_VOLTAGE_4P5V; /*配置VREFP输出电压*/
#endif

    VREFP_InitStruct.mode          = FL_VREFP_WORK_MODE_CONTINUOUS; /*配置VREFP输出模式*/
    VREFP_InitStruct.timeOfPeriod  = FL_VREFP_ENABLE_PERIOD_1MS;    /*配置VREFP间歇模式的周期*/
    VREFP_InitStruct.timeOfDriving = FL_VREFP_DRIVING_TIME_4LSCLK;  /*配置VREFP间歇模式的驱动时间*/
    (void)FL_VREFP_Init(VREFP, &VREFP_InitStruct);
}

void Bsp_DAC_init(void)
{
    FL_DAC_InitTypeDef DAC_InitStruct;
    FL_OPA_InitTypeDef OPA_InitStruct;
    uint8_t            i = 0;

    /* Initial VREFP ，初始化给DAC，ADC供电选择为Vrefp*/
    VREFP_Init();

    // 控制引脚初始化
    for (i = 0; i < (sizeof(dac_ctl_pin) / sizeof(dac_ctl_pin[0])); i++) {
        FL_GPIO_Init(dac_ctl_pin[i].GPIOx, &dac_ctl_pin[i].init_type);
        FL_GPIO_ResetOutputPin(dac_ctl_pin[i].GPIOx, dac_ctl_pin[i].init_type.pin);
    }

#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
    DAC_InitStruct.triggerMode    = FL_DISABLE;
    DAC_InitStruct.triggerSource  = FL_DAC_TRGI_SOFTWARE;
    DAC_InitStruct.sampleHoldMode = FL_DISABLE;
    DAC_InitStruct.holdTime       = 0x0;
    DAC_InitStruct.sampleTime     = 0x0;
    DAC_InitStruct.bufferMode     = FL_DISABLE;
    DAC_InitStruct.switchMode     = FL_DISABLE;
    FL_DAC_Init(DAC, &DAC_InitStruct);

    // OPA init
    OPA_InitStruct.INP           = FL_OPA_INP_SOURCE_DAC;
    OPA_InitStruct.INN           = FL_OPA_INN_SOURCE_INN1;
    OPA_InitStruct.mode          = FL_OPA_MODE_BUFFER;
    OPA_InitStruct.PGAModeSelect = FL_OPA_PGA_MODE_FB_TO_GND;
    OPA_InitStruct.negtiveToPin  = FL_DISABLE;
    OPA_InitStruct.gain          = FL_OPA_GAIN_NOINVERT_X2;
    OPA_InitStruct.lowPowermode  = FL_DISABLE;
    FL_OPA_Init(OPA, &OPA_InitStruct);

    FL_DAC_Enable(DAC);
    FL_DAC_WriteData(DAC, DAC_VALUE_INIT);
    FL_OPA_Enable(OPA);

    Dac_value_init();
#elif defined(HARD_VERSION_V2_1)

#endif

    (void)DAC_InitStruct;
    (void)OPA_InitStruct;
}

/**
 * TODO:ADC转换流程如下：
 * //ADC初始化使用定时器触发采样，
 * 1. 更新对应GPIO；
 * 2.开启定时器10ms中断，确保电路建立稳态；
 * 3.定时器中断开启adc转换
 * 4.adc中断计算adc值是否符合要求，
 *  若不符合，调整DAC输出，跳转执行2；
 *  若符合，测量下一路，跳转流程1，
 */

// 根据表查找当前DAC数据是否有效，若有效，则下一步，若无效，则根据表格跳转下一个挡位
// TODO:硬件差异配置项，，为避免波动，table的不同挡位之间应有重复
#if defined(HARD_VERSION_V1)
/* 阻值计算： Rp=R_cfg*Kop*Xdac/(Xadc-Kop*Xdac)  **/
const CFG_Table DAC_table[] = {
    // Xdac,kop,Xadc_min Xadc_max
    { 500, 1, 600, 3200 },   // 0.15-2.15(Kohm)
    { 1000, 1, 1200, 3200 }, // 2.15-16.7(Kohm)
    { 2500, 1, 2551, 3200 }, // 16.7-230.4(Kohm)
};
#elif defined(HARD_VERSION_V2)
/*阻值计算： Rp=R_cfg*Xadc/(Xdac*Kop-Xadc)  **/
const CFG_Table DAC_table[] = {
    //{3250,1,1583,3249},//4.463-300.8(Kohm),Xadc>3200精度失真，仅供参考
    { 3250, 1, 1583, 3200 }, // 4.463-300.8(Kohm)
    //{3900,1,1000,3800}, //0.69-4.465(Kohm)
};
#endif

static uint8_t Cur_table_index = 0;

void Dac_value_init(void)
{
#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))

    Cur_table_index = 0;
    FL_DAC_WriteData(DAC, DAC_table[Cur_table_index].Xdac);
#endif
}

// 动态调整DAC的输出值，使得ADC更精确
uint8_t DAC_value_adj(uint16_t Xadc, float *res_val)
#if (defined(HARD_VERSION_V1) || defined(HARD_VERSION_V2))
{
    uint8_t return_val = 0;

    if (Xadc > DAC_table[Cur_table_index].Xadc_max) { // 需减小Xadc,则相应减小Xdac
        // 但Xdac按照下标增而增大，无可减小，直接按照当前挡位数据解析
        return_val = 1;
    }
    else if (Xadc < DAC_table[Cur_table_index].Xadc_min) { // 需增大Xadc，则相应增大Xdac
        if (Cur_table_index + 1 < (sizeof(DAC_table) / sizeof(DAC_table[0]))) {
            Cur_table_index++;
        }
        else {
            // 调整到极限
            return_val = 2;
        }
    }
    else {
        // Xadc有效，取值
        return_val = 3;
    }

    // ADC有效，计算对应阻值
    if ((0 != return_val)) {
        *res_val = RES_CAL(DAC_table[Cur_table_index].Xdac, Xadc);
        if (*res_val > RES_VALUE_MAX) {
            *res_val = RES_VALUE_INVALID;
        }
        // 初始化相关数据
        Cur_table_index = 0;
    }

    // 写DAC
    FL_DAC_WriteData(DAC, DAC_table[Cur_table_index].Xdac);

    return return_val;
}
#elif defined(HARD_VERSION_V2_1)
{
    *res_val = RES_CAL(0, Xadc);
    if (*res_val > RES_VALUE_MAX) {
        *res_val = RES_VALUE_INVALID;
    }

    return 1;
}
#endif
